// -----------------------------------------------------------------------------
// Copyright (c) 2014-2024 All rights reserved
// -----------------------------------------------------------------------------
// Author 		: HiDark 1173296519@qq.com
// File   		: cordic_sqrt.v
// Create 		: 2024-01-03 11:44:35
// Description	: cordic vector mode in hyperbolic system,16 levels pipeline
// Editor 		: tab size (4)
// -----------------------------------------------------------------------------
module cordic_sqrt (
	input 				clk,    // Clock
	input 				rst_n,  // Asynchronous reset active low
	input		[31:0]	din,    
	input				vld_in, 

	output				vld_out, 
	output		[31:0]	dout  
);
//Compensation factor
localparam K   =  32'd79135  ;     //1.20749706*2^16
// all operations must be signed
// [0] is initial ,[1] is first iteration
reg signed  [31:0]  x   [15:0];
reg signed  [31:0]  y   [15:0];
reg 		[15:0]  vld ;
// initial 
always @(posedge clk or negedge rst_n) begin
	if(~rst_n) begin
		x[0]   <= 32'b0;
		y[0]   <= 32'b0;
		vld[0] <= 1'b0;		
	end else if(vld_in)begin 
		x[0]   <= din + 1;
		y[0]   <= din - 1;
		vld[0] <= vld_in;
	end
end
//-----------------------------------------------------------------
// Pipeline
//-----------------------------------------------------------------
//vld pipeline
genvar j;
generate
	for (j = 1; j <= 16; j=j+1) begin
		always @(posedge clk) 
			vld[j] <= vld[j-1];
	end
endgenerate
//1~4 iteration
genvar i;
generate
	for (i = 1; i < 4; i=i+1) begin
		always @(posedge clk) begin
			if(y[i-1] == 0) begin
				x[i] <= x[i-1] - (y[i-1]>>>i); 
				y[i] <= y[i-1] - (x[i-1]>>>i);	
			end else begin
				x[i] <= x[i-1] + (y[i-1]>>>i); 
				y[i] <= y[i-1] + (x[i-1]>>>i);		
			end
		end
	end
endgenerate
//5th iteration (repeat 4 ,1 2 3 4 4)
	always @(posedge clk) begin
		if(y[3] == 0) begin
			x[4] <= x[3] - (y[3]>>>3); 
			y[4] <= y[3] - (x[3]>>>3);	
		end else begin
			x[4] <= x[3] + (y[3]>>>3); 
			y[4] <= y[3] + (x[3]>>>3);		
		end
	end
//6~13 iteration
generate
	for (i = 5; i < 14; i=i+1) begin
		always @(posedge clk) begin
			if(y[i-1] == 0) begin
				x[i] <= x[i-1] - (y[i-1]>>>(i-1)); 
				y[i] <= y[i-1] - (x[i-1]>>>(i-1));	
			end else begin
				x[i] <= x[i-1] + (y[i-1]>>>(i-1)); 
				y[i] <= y[i-1] + (x[i-1]>>>(i-1));		
			end
		end
	end
endgenerate
//15th iteration (repeat 13th)
	always @(posedge clk) begin
		if(y[13] == 0) begin
			x[14] <= x[13] - (y[13]>>>12); 
			y[14] <= y[13] - (x[13]>>>12);	
		end else begin
			x[14] <= x[13] + (y[13]>>>12); 
			y[14] <= y[13] + (x[13]>>>12);		
		end
	end
//16th iteration
	always @(posedge clk) begin
		if(y[14] == 0) begin
			x[15] <= x[14] - (y[14]>>>13); 
			y[15] <= y[14] - (x[14]>>>13);	
		end else begin
			x[15] <= x[14] + (y[14]>>>13); 
			y[15] <= y[14] + (x[14]>>>13);		
		end
	end
// result
assign dout 	= x[15] * K/2;
assign vld_out 	= vld[15];
endmodule 